<template>
    <div class="app-container">
        <el-form :inline="true" :model="query" size="mini">
            <el-form-item label="用户名：">
                <!-- “trim()”方法被用于删除输入的字符串两端的空格↓ -->
                <el-input v-model.trim="query.username" placeholder="用户名"></el-input>
            </el-form-item>
            <el-form-item label="手机号：">
                <el-input v-model.trim="query.mobile" placeholder="手机号"></el-input>
            </el-form-item>
            <el-form-item>
                <el-button icon="el-icon-search" type="primary" @click="queryData">查询</el-button>
                <el-button icon="el-icon-refresh" @click="reload">重置</el-button>
                <el-button icon="el-icon-circle-plus-outline" type="primary" @click="openDialogAndAdd">新增</el-button>
            </el-form-item>
        </el-form>
        <el-table :data="list" :cell-style="rowStyle" align="center" stripe border style="width: 100%">
            <el-table-column type="index" align="center" label="序号" width="60"></el-table-column>
            <el-table-column prop="username" align="center" label="用户名"></el-table-column>
            <el-table-column prop="nickName" align="center" label="昵称"></el-table-column>
            <el-table-column prop="mobile" align="center" label="手机号"></el-table-column>
            <el-table-column prop="email" align="center" label="邮箱"></el-table-column>
            <el-table-column prop="isAccountNonExpired" align="center" label="账户过期">
                <!-- 1：正常；0：过期 -->
                <template slot-scope="scope">
                    <!-- 注意：只有当“isAccountNonExpired”在此处的取值为“1”时，三元表达式才会取第一个值，表示“未过期”↓ -->
                    <!-- <el-tag :type="scope.row.isAccountNonExpired | isAccountNonExpiredFilter">{{scope.row.isAccountNonExpired ? '未过期' : '已过期'}}</el-tag> -->
                    <el-tag v-if="scope.row.isAccountNonExpired === 0" type="danger">过期</el-tag>
                    <el-tag v-if="scope.row.isAccountNonExpired === 1" type="success">正常</el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="isAccountNonLocked" align="center" label="账户锁定">
                <!-- 1：正常；0：锁定 -->
                <template slot-scope="scope">
                    <el-tag v-if="scope.row.isAccountNonLocked === 0" type="danger">锁定</el-tag>
                    <el-tag v-if="scope.row.isAccountNonLocked === 1" type="success">正常</el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="isCredentialsNonExpired" align="center" label="密码过期">
                <!-- 1：正常；0：过期 -->
                <template slot-scope="scope">
                    <el-tag v-if="scope.row.isCredentialsNonExpired === 0" type="danger">过期</el-tag>
                    <el-tag v-if="scope.row.isCredentialsNonExpired === 1" type="success">正常</el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="isEnabled" align="center" label="是否可用">
                <!-- 1：可用；0：已删除用户 -->
                <template slot-scope="scope">
                    <el-tag v-if="scope.row.isEnabled === 0" type="danger">已删除</el-tag>
                    <el-tag v-if="scope.row.isEnabled === 1" type="success">可用</el-tag>
                </template>
            </el-table-column>
            <el-table-column align="center" label="操作" width="323">
            <!-- “scope”代表当前行的对象，可以通过它来获取当前行的某个属性值↓ -->
                <template slot-scope="scope" v-if="scope.row.isEnabled === 1">
                    <el-button type="success" size="mini" @click="handleEdit(scope.row.id)">编辑</el-button>
                    <el-button type="danger" size="mini" @click="handleDelete(scope.row.id)">删除</el-button>
                    <el-button type="primary" size="mini" @click="handleRole(scope.row.id)">设置角色</el-button>
                    <el-button size="mini" @click="handlePwd(scope.row.id)">密码修改</el-button>
                </template>
            </el-table-column>
        </el-table>
        <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page.current" :page-sizes="[10, 20, 50]" :page-size="page.size" layout="total, sizes, prev, pager, next, jumper" :total="page.total"></el-pagination>
        <!-- 编辑组件↓ -->
        <edit :title="edit.title" :dialogVisible="edit.visible" :formData="edit.formData" :remoteClose="remoteClose" />
        <el-dialog title="设置角色" center :visible.sync="role.dialogVisible" width="65%">
            <!-- “roleIds”是当前用户所拥有的角色ID，“saveUserRole”事件是由子组件触发提交选择的角色ID的事件↓ -->
            <Role :roleIds="role.roleIds" @saveUserRole="saveUserRole" />
        </el-dialog>
        <!-- 密码修改组件↓ -->
        <password title="修改密码" :userId="password.userId" :dialogVisible="password.visible" :remoteClose="remotePasswordClose"/>
    </div>
</template>

<script>
// import {getList} from '@/api/user' // ←按需导入某个方法，使用“解构”的方式指定被导入的方法
import * as api from '@/api/user' // ←导入所有被导出的方法，其中星号代表所有被导出的方法。采用该方式导入的方法后面需使用时，直接采用“别名.方法名()”的方式即可
import Edit from './edit'
import Password from './password'
import Role from '../role' // ←注意：此处无需在“role”后加“/index”或“/index.vue”，因为浏览器会自动去找这个文件
export default {
    name: 'User', // ←注意：左边这项的值要和路由表中配置的“name”的值保持一致
    components: {Edit,Role,Password}, // ←注意：左边这项中的“Edit”相当于ES5中的“Edit:Edit”,“Role”相当于ES5中的“Role:Role”
    data() {
        return {
            list:[],
            page:{
                current:1,
                size:20,
                total:0
            },
            query:{},
            total:0, // ←左边这项表示“总记录数”
            edit:{ // ←注意：左边这项表示“子组件引用的属性对象”
                title:'',
                visible:false,
                formData:{}
            },
            role:{ // ←左边这项表示“弹出‘设置角色’组件”
                dialogVisible:false,
                // 传递到子组件中时至少会传递一个空数组“[]”，可以供子组件判断“roleIds”是否有值↓
                roleIds:[], // ←左边这项表示“封装当前用户所拥有的角色ID”（注：即使当前用户没有默认拥有的角色，在传值时被我们传递的对象也应该是一个空数组而非空值“null”（因为空数组还是有值的））
                userId:null, // ←左边这项在保存用户拥有的角色时需要使用，点击了哪个用户，就是该用户的ID
            },
            password:{ // ←左边这项表示“‘修改密码’组件引用的属性对象”
                userId:null, // ←左边这项表示“修改哪一个用户”
                visible:false
            }
        }
    },
    created() {
        this.fetchData()
    },
    methods: {
        async fetchData(){
            const {data} = await api.getList(this.query,this.page.current,this.page.size) // ←注：左边这项采用了“解构赋值”的形式（具体为返回的“response.data”的值被赋值给了“{data}”中的“data”）
            // getList(this.query,this.page.current,this.page.size) // 当上面↑按需导入某个方法，使用“解构”的方式指定被导入的方法时，左边这行最顶端就无需写上“api.”
            this.list = data.records
            this.page.total = data.total
        },
        // “value”表示“切换之后每页显示的条数”↓
        handleSizeChange(value){
            this.page.size = value
            this.fetchData()
        },
        // 当页码改变后触发此方法，“value”表示“当前点击或输入的（即改变后的）那个页码”↓
        handleCurrentChange(value){
            this.page.current = value
            this.fetchData()
        },
        // 条件查询
        queryData(){
            // 将页码变为“第1页”
            this.page.current = 1
            this.fetchData()
        },
        // 重置
        reload(){
            this.query = {}, // ←左边这一项表示“向‘this.query’传递空对象”
            this.fetchData()
        },
        // 编辑用户
        handleEdit(id){
            // console.log('编辑',id)
            // 通过ID查询详情
            api.getById(id).then(response => {
                if (response.code === 20000) {
                    // 将查询到的详情数据传递过来
                    this.edit.formData = response.data
                    this.edit.title = '编辑'
                    this.edit.visible = true
                }
            })
        },
        // 删除用户
        handleDelete(id){
            console.log('删除',id)
            this.$confirm('确认删除这条记录吗?', '提示', { // 技巧：按组合键“Shift+Tab”会让代码向左缩进
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning',
                center: true
            }).then(() => {
                // 发送删除请求
                api.deleteById(id).then(response => {
                    // 处理响应结果
                    this.$message({
                        type: response.code === 20000 ? 'success' : 'error',
                        message: response.message,
                        center:true,
                    });
                })
                // 刷新列表数据
                this.fetchData()
            }).catch(() => {
                // 点击“取消”按钮，取消删除。此处无需做任何逻辑处理（即“不用理会”，因为浏览器会自动关闭消息提示框）          
            });
        },
        // 设置角色
        handleRole(id){
            this.role.userId = id
            api.getRoleIdsByUserId(id).then(response =>{
                // 在此处已经拿到了角色ID，并且角色ID已被传递给作为子组件的“角色管理”模块（组件）
                this.role.roleIds = response.data
                // 弹出对话框
                this.role.dialogVisible = true
            })
        },
        // 密码修改
        handlePwd(id){
            // 要修改的用户ID
            this.password.userId = id
            this.password.visible = true
        },
        // 打开“新增”对话框
        openDialogAndAdd(){
            this.edit.visible = true
            this.edit.title = '新增(注：默认密码与用户名一致)'
        },
        // 子组件会触发此事件来关闭对话框
        remoteClose(){
            this.edit.formData = {}
            this.edit.visible = false
            this.fetchData() // ←注：如果关闭对话框后不想或无需刷新列表数据，则无需调用左边的这个方法
        },
        // 角色列表（子组件会触发此事件来保存当前用户选择的角色ID）
        saveUserRole(checkedRoleIds){
            // console.log('saveUserRole',checkedRoleIds)
            // 保存用户角色信息
            api.saveUserRole(this.role.userId,checkedRoleIds).then(response => {
                if (response.code === 20000) {
                    this.$message({
                        message:'分配角色成功',
                        type:'success',
                        center:true
                    })
                    this.role.dialogVisible = false
                } else {
                    this.$message({
                        message:'分配角色失败',
                        type:'error',
                        center:true
                    })
                }
            })
        },
        // 关闭“修改密码”对话框
        remotePasswordClose(){
            this.password.userId = null
            this.password.visible = false
            this.fetchData()
        },
        rowStyle(){
            return "text-align:center";
        },
    },
}
</script>
<style lang="scss" scoped>
    div{::v-deep.el-input__inner{text-align: center;}}
    .el-pagination , .el-select-dropdown__item {text-align: center;}
</style>